package com.jim.director.framework.validation;

import com.jim.director.framework.annotation.Actor;
import com.jim.director.framework.annotation.ActorAutowired;
import com.jim.director.framework.annotation.Configure;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * 依赖注入注解校验器
 * 校验@ActorAutowired注解的合法性
 *
 * @author Jim
 * @date 2024/10/5
 */
public class DependencyValidator implements AnnotationValidator {

    // 支持的集合类型
    private static final Set<String> SUPPORTED_COLLECTION_TYPES = new HashSet<>(Arrays.asList(
        "java.util.List",
        "java.util.ArrayList",
        "java.util.LinkedList",
        "java.util.Set",
        "java.util.HashSet",
        "java.util.LinkedHashSet",
        "java.util.Collection"
    ));

    @Override
    public ValidationResult validate(Class<?> clazz) {
        ValidationResult result = new ValidationResult(clazz.getSimpleName());

        // 只校验带有@Actor注解的类
        if (!clazz.isAnnotationPresent(Actor.class) && !clazz.isAnnotationPresent(Configure.class)) {
            return result;
        }

        // 校验@Actor注解的size参数
        if (clazz.isAnnotationPresent(Actor.class)) {
            validateActorSize(clazz, result);
        }

        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            // 校验@ActorAutowired
            if (field.isAnnotationPresent(ActorAutowired.class)) {
                validateActorAutowired(field, result, clazz);
            }
        }

        return result;
    }

    /**
     * 校验@Actor注解的size参数
     */
    private void validateActorSize(Class<?> clazz, ValidationResult result) {
        Actor actor = clazz.getAnnotation(Actor.class);
        int size = actor.size();

        if (size <= 0) {
            result.addError(String.format(
                "类 %s 的 @Actor 注解: size参数值 %d 必须大于0。",
                clazz.getSimpleName(), size
            ));
        }

        if (size > 1000) {
            result.addWarning(String.format(
                "类 %s 的 @Actor 注解: size参数值 %d 较大，" +
                "可能影响性能。建议评估是否真的需要这么多实例。",
                clazz.getSimpleName(), size
            ));
        }
    }

    /**
     * 校验@ActorAutowired注解
     */
    private void validateActorAutowired(Field field, ValidationResult result, Class<?> clazz) {
        // 1. 校验字段访问修饰符
        validateFieldModifiers(field, result, clazz, "@ActorAutowired");

        // 2. 校验字段类型
        Class<?> fieldType = field.getType();

        if (Collection.class.isAssignableFrom(fieldType)) {
            // 集合类型字段
            validateCollectionField(field, result, clazz);
        } else {
            // 单个对象字段
            validateSingleObjectField(field, result, clazz);
        }

        // 3. 检查自依赖
        if (fieldType.equals(clazz)) {
            result.addError(String.format(
                "类 %s 的字段 %s 标注了 @ActorAutowired 注解，但字段类型是自身类型。" +
                "Actor不能依赖注入自己。",
                clazz.getSimpleName(), field.getName()
            ));
        }
    }

    /**
     * 校验单个对象字段
     */
    private void validateSingleObjectField(Field field, ValidationResult result, Class<?> clazz) {
        Class<?> fieldType = field.getType();

        if (!isActorType(fieldType)) {
            result.addError(String.format(
                "类 %s 的字段 %s 标注了 @ActorAutowired 注解，但字段类型 %s 没有标注 @Actor 注解。" +
                "只有标注了 @Actor 或 @Configure 的类才能被注入。请检查 %s 类是否正确标注了相关注解。",
                clazz.getSimpleName(), field.getName(), fieldType.getSimpleName(), fieldType.getSimpleName()
            ));
        }
    }

    /**
     * 校验集合字段
     */
    private void validateCollectionField(Field field, ValidationResult result, Class<?> clazz) {
        Class<?> fieldType = field.getType();

        // 1. 校验集合类型是否被支持
        String fieldTypeName = fieldType.getName();
        if (!SUPPORTED_COLLECTION_TYPES.contains(fieldTypeName)) {
            result.addWarning(String.format(
                "类 %s 的字段 %s 的集合类型 %s 可能不被完全支持。" +
                "建议使用 List、ArrayList、Set、HashSet 或 Collection 类型。",
                clazz.getSimpleName(), field.getName(), fieldType.getSimpleName()
            ));
        }

        // 2. 校验泛型参数
        validateGenericType(field, result, clazz);
    }

    /**
     * 校验泛型参数
     */
    private void validateGenericType(Field field, ValidationResult result, Class<?> clazz) {
        Type genericType = field.getGenericType();

        if (!(genericType instanceof ParameterizedType)) {
            result.addWarning(String.format(
                "类 %s 的字段 %s 使用了原始集合类型，没有指定泛型参数。" +
                "建议指定泛型参数，如: List<SomeActor> %s;",
                clazz.getSimpleName(), field.getName(), field.getName()
            ));
            return;
        }

        ParameterizedType parameterizedType = (ParameterizedType) genericType;
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

        if (actualTypeArguments.length != 1) {
            result.addError(String.format(
                "类 %s 的字段 %s 的集合泛型参数配置错误。" +
                "集合应该只有一个泛型参数，如: List<ActorType>。",
                clazz.getSimpleName(), field.getName()
            ));
            return;
        }

        Type elementType = actualTypeArguments[0];
        if (elementType instanceof Class<?>) {
            Class<?> elementClass = (Class<?>) elementType;

            // 检查元素类型是否为Actor
            if (!isActorType(elementClass)) {
                result.addError(String.format(
                    "类 %s 的字段 %s 的集合元素类型 %s 没有标注 @Actor 注解。" +
                    "只有标注了 @Actor 或 @Configure 的类才能被集合注入。",
                    clazz.getSimpleName(), field.getName(), elementClass.getSimpleName()
                ));
            }
        }
    }

    /**
     * 校验字段访问修饰符
     */
    private void validateFieldModifiers(Field field, ValidationResult result, Class<?> clazz, String annotationName) {
        if (Modifier.isStatic(field.getModifiers())) {
            result.addError(String.format(
                "类 %s 的字段 %s 标注了 %s 注解，但是static字段。" +
                "依赖注入不支持静态字段。",
                clazz.getSimpleName(), field.getName(), annotationName
            ));
        }

        if (Modifier.isFinal(field.getModifiers())) {
            result.addError(String.format(
                "类 %s 的字段 %s 标注了 %s 注解，但是final字段。" +
                "final字段无法被依赖注入修改。",
                clazz.getSimpleName(), field.getName(), annotationName
            ));
        }
    }

    /**
     * 检查类型是否为Actor类型
     */
    private boolean isActorType(Class<?> type) {
        return type.isAnnotationPresent(Actor.class) || type.isAnnotationPresent(Configure.class);
    }

    @Override
    public Class<?>[] getSupportedAnnotations() {
        return new Class<?>[]{ActorAutowired.class};
    }

    @Override
    public String getValidatorName() {
        return "DependencyValidator";
    }
}

